﻿using System;
using System.Diagnostics;
using Mjolnir.InfraEstrutura.Servicos;

namespace Mjolnir.Modelo.Histogramas
{
  public class ServicoHistograma : ServicoBase<Histograma, FabricaHistograma>, IServicoHistograma
  {
    public ServicoHistograma()
      : base()
    {
    }

    /// <summary>
    /// Obter o total (getTotal).
    /// </summary>
    /// <param name="min">mínimo.</param>
    /// <param name="max">máximo.</param>
    /// <returns></returns>
    public int obterTotal(int min, int max)
    {
      Debug.Assert(min < max && max < entidade.tamanho);

      int resultado = 0;
      int[] s = entidade.valor;

      for (int i = min; i < max; i++)
      {
        resultado += s[i];
      }

      return resultado;
    }

    /// <summary>
    /// Cortar ate posição desejada (lowCut).
    /// </summary>
    /// <param name="posicao">posicao desejada.</param>
    public void cortarAte(int posicao)
    {
      int s = 0;

      for (int i = 0; i < posicao; i++)
      {
        s += entidade.valor[i];
        entidade.valor[i] = 0;
      }

      entidade.valorTotal -= s;
    }

    /// <summary>
    /// Cortar desde posição desejada (highCut).
    /// </summary>
    /// <param name="posicao">posicao desejada.</param>
    public void cortarDesde(int posicao)
    {
      int s = 0;

      for (int i = entidade.tamanho; i >= posicao; i--)
      {
        s += entidade.valor[i];
        entidade.valor[i] = 0;
      }

      entidade.valorTotal -= s;
    }

    /// <summary>
    /// Obter índice minimo (getMinSample).
    /// </summary>
    /// <returns></returns>
    public int obterIndiceMinimo()
    {
      int[] valor = entidade.valor;
      int retorno = entidade.tamanho - 1;
      int minimo = valor[retorno];

      for (int i = entidade.tamanho - 2; i >= 0; i--)
      {
        if (valor[i] < minimo)
        {
          minimo = valor[i];
          retorno = i;
        }
      }

      return retorno;
    }

    /// <summary>
    /// Obter o valor minimo (getMinData).
    /// </summary>
    /// <returns></returns>
    public int obterValorMinimo()
    {
      return entidade.valor[this.obterIndiceMinimo()];
    }

    /// <summary>
    /// Obter a media (getAvarage).
    /// </summary>
    /// <returns></returns>
    public int obterMedia()
    {
      long soma = 0;

      for (int i = entidade.tamanho; i >= 0; i--)
      {
        soma += entidade.valor[i] * i;
      }

      return Convert.ToInt32(soma / entidade.valorTotal);
    }
  }
}
